home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 3
/
Gold Medal Software - Volume 3 (Gold Medal) (1994).iso
/
utils2
/
mymous12.arj
/
SCREENTA.ASM
< prev
Wrap
Assembly Source File
|
1994-01-07
|
10KB
|
224 lines
; MyMouse
; Bit to handle screen-activewindow associative table
; Andrew Forrest
;****************************************************************************
; The program manages the table as a linked list of blocks. Each block
; contains up to a maximum number of (screen, activewindow) pairs. The head
; of the list is the most recently-accessed pair.
; All these routines should be called with Intuitionbase locked.
; No arbitration is done for access to screen table, so only one task at a
; time please.
;***************************************************************************
; USES:
; Globals.ScreenTable (the abstract object itself)
; EXPORTS:
; InitialiseScreenTable() ; Call this first
; ShutDownScreenTable() ; Call this last
; AssociateWindow(Screen, Window) ; Insert a tuple in the table
; IndexScreenTable(Screen) : Window ; Look up a tuple
; PruneScreenTable() ; Remove redundant entries
;
;***************************************************************************
; Table is represented as a linked list of blocks, each with up to
; TuplesPerChunk tuples. (Each chunk in the table is an Exec minnode.)
; The last chunk may be partially-empty, in which case the remaining spaces
; are filled with NULL screen pointers. It is vitally important (to
; PruneScreenTable()) that _only_ the last node is padded with NULLs.
; ScreenTable.LastTupleOffset is the offset (from its chunk) of the last
; non-NULL tuple in the table. This can be 0 is last node is empty (entirely
; NULL) or undefined if there are no chunks. FirstTupleOffset is unused.
TuplesPerChunk equ 7 ; Ideally a power of 2 minus 1
STRUCTURE ScreenWindowTuple,0
APTR Tuple_Screen
APTR Tuple_Window
LABEL Tuple_SIZEOF
STRUCTURE ScreenTableChunk,MLN_SIZE
STRUCT Chunk_Data,Tuple_SIZEOF*TuplesPerChunk
LABEL Chunk_SIZEOF
STRUCTURE ScreenTableType,MLH_SIZE
WORD ST_FirstTupleOffset ; \ Byte offset from chunk to
WORD ST_LastTupleOffset ; / start of first/last tuple
LABEL ST_SIZEOF
; PRIVATE routine to find the tuple associated with a particular screen if it
; can be found. Takes a0=^screen; Uses a5=^globals (for ScreenTable)
; Returns (d0=^chunk; d1=tup offset | d0=NULL; d1=?); Trashes nil.
FindScreenTuple:
pushm.l a1/d2
move.l a0,d0 ;\ Return a NULL if
beq.s .null ;/ ^screen is NULL
move.l ScreenTable+MLH_HEAD(a5),a1
.loop move.l MLN_SUCC(a1),d0 ; d0 <- node after this one
beq.s .null ; fail if this is not really a node (the `next node' of the list header TAILPRED is NULL)
moveq #Chunk_Data,d1 ; d1 <- offset of first tuple
moveq #TuplesPerChunk-1,d2
.dataloop cmp.l Tuple_Screen(a1,d1),a0
beq.s .succeed ; Exit early if we _do_ find the screen
addq.l #Tuple_SIZEOF,d1 ; Get to next bit of data
dbra d2,.dataloop
move.l d0,a1 ; Get the next node
bra.s .loop
.succeed move.l a1,d0 ; d0 <- ^this chunk
.null popm.l a1/d2 ; If we jump to here, d0 will equal NULL
rts
; Routine to make screen table ready for use. Allocates all the necessary
; resources. Structure must initially be zeroed.
; Uses a5=^Globals (for ScreenTable); Trashes & Returns nil;
InitialiseScreenTable:
; << Shares code with ShutDownScreenTable >>
; Routine to deallocate all of the screen table's resources and generally
; shut up shop. May be called even if structure is uninitialised (zeroed).
; Leaves screen table in an initialised state. (Deallocation is done
; without keeping the list consistant betweentimes.)
; Uses a5=^Globals (for ScreenTable)
ShutDownScreenTable:
pushm.l a0-a2/d0-d2/a6
move.l Execbase,a6
lea ScreenTable+MLH_HEAD(a5),a2
move.l (a2),d2
beq.s .end ; Quit early if not initialised
.loop move.l d2,a1 ; thisnode <- nextnode
move.l MLN_SUCC(a1),d2 ; nextnode <- thisnode.NEXT
beq.s .end ; Exit if no next node (in list header)
move.l #Chunk_SIZEOF,d0
just FreeMem ; Free the memory of this node
bra.s .loop ; Keep looping 'til end of list
.end NEWLIST a2 ; Make listheader self-consistant again
clr.l ScreenTable+ST_FirstTupleOffset(a5) ; Clears TWO words
popm.l a0-a2/d0-d2/a6
rts
; Routine to associate a particular window with a particular screen.
; Takes a0=^screen; a1=^window; Returns nil; Trashes nil.
; Uses a5=^globals (for ScreenTable and (locked) Intbase)
; Uses a2=^tuple; d1=last tuple offset; also a2,a3 = pointers to chunks
AssociateWindow:
cmp.w #0,a0 ; \ First check that we have not been
beq.s .return ; / passed a NULL screen pointer
pushm.l a2-a3/d0-d1
bsr FindScreenTuple
move.l d0,a2 ; a2 <- pointer to chunk
tst.l d0
bne.s .found ; If FindScreenTuple(..) == NULL
move.l ScreenTable+MLH_TAILPRED(a5),a2 ; Get last chunk
tst.l MLN_PRED(a2) ; Does it have a predecessor?
beq.s .new_chunk ; (If not, it isn't a proper node)
move.w ScreenTable+ST_LastTupleOffset(a5),d1
addq.w #Tuple_SIZEOF,d1 ; Compute new LastTuple offset
cmp.w #Chunk_SIZEOF,d1
blo.s .enoughroom ; If last chunk is full up...
.new_chunk pushm.l a0-a1/a6
move.l Execbase,a6
move.l #Chunk_SIZEOF,d0
move.l #MEMF_CLEAR,d1
just AllocMem ; ...allocate a new one
popm.l a0-a1/a6
tst.l d0
beq.s .end ; (Can't allocate memory, so give up)
move.l d0,MLN_SUCC(a2)
exg d0,a2 ; d0 <- ^prev chunk; a2 <- ^new chunk
move.l d0,MLN_PRED(a2)
lea ScreenTable+MLH_TAIL(a5),a3 ; a3 <- ^next chnk
move.l a2,MLN_PRED(a3)
move.l a3,MLN_SUCC(a2)
moveq #Chunk_Data,d1
.enoughroom move.w d1,ScreenTable+ST_LastTupleOffset(a5)
move.l a0,Tuple_Screen(a2,d1.w)
.found move.l a1,Tuple_Window(a2,d1.w)
.end popm.l a2-a3/d0-d1
.return rts
; Routine to look up a screen in the table and return its associated window.
; Checks for existance of window. If window not in screen, returns frontmost
; window. WARNING: does not check for the existance of the screen (but does
; accept a NULL screen pointer, to which it returns NULL).
; Takes a0=^screen. Uses a5=^globals (uses ScreenTable and (locked) Intbase)
; Returns d0=^window. Trashes nil.
IndexScreenTable:
pushm.l a0-a1/d1
bsr FindScreenTuple
tst.l d0
beq.s .end ; Exit with d0=null if can't find screen
move.l d0,a1
move.l Tuple_Window(a1,d1.w),d0
move.l sc_FirstWindow(a0),d1 ; Get first window in screen
.windloop beq.s .closed ; Return front window if no more windows
cmp.l d1,d0 ; Is this the window we seek?
beq.s .end ; Found window in screen: success
move.l d1,a1
move.l wd_NextWindow(a1),d1 ; Else look at _next_ window
bra.s .windloop ; Keep looping 'til no more windows
.end popm.l a0-a1/d1
rts
.closed move.l sc_FirstWindow(a0),d0 ; Return the frontmost window
bra.s .end ; ...and exit
; This routine garbage-collects non-existant (closed) screens from the table.
; Takes nil; Uses a5=^globals (for ScreenTable and (locked) Intbase)
; Returns nil; Trashes nil.
; Uses a0=^this chunk; d0=tuple offset; a1=^last chunk; d1=last tuple offset
; a2=^first screen; d2=^search screen; a3=^this screen; d3=tuple count
; a6=^execbase
PruneScreenTable:
pushm.l a0-a3/a6/d0-d3
move.w ScreenTable+ST_LastTupleOffset(a5),d1
move.l Execbase,a6
move.l IntBase(a5),a2
move.l ib_FirstScreen(a2),a2
lea ScreenTable+MLH_HEAD(a5),a0
move.l ScreenTable+MLH_TAILPRED(a5),a1 ; (It's okay: we check to see if the first node exists, and if _it_ exists, there must be a last node too.)
.nextchunk move.l MLN_SUCC(a0),a0 ; Get next chunk after this
tst.l MLN_SUCC(a0) ; (Do it this way in case the successor node changes (is removed) while we have a cached next-node pointer, for example.)
beq.s .endchunks ; Exit if we are back to list header
moveq #Chunk_Data,d0 ; Offset of actual data
moveq #TuplesPerChunk-1,d3 ; Repeat TuplesPerChunk times
.tupleloop move.l Tuple_Screen(a0,d0.w),d2 ; Get next tuple in chunk
beq.s .endchunks ; NULL screen occurs only at end of list
lea (a2),a3 ; Get the first screen on the system list
.screenloop cmp.l a3,d2 ; Is this the screen we are looking for?
beq.s .nexttuple ; If found, on to next tuple
cmp.w #0,a3 ; End of screen list?
movea.l sc_NextScreen(a3),a3 ; (CCR unaffected)
bne.s .screenloop ; Stop looping at list end
bsr.s .removescrn
.nexttuple addq.w #Tuple_SIZEOF,d0 ; Offset of next datum
dbra d3,.tupleloop ; Loop on TuplesPerChunk
bra.s .nextchunk ; Loop on chunks
.endchunks move.w d1,ScreenTable+ST_LastTupleOffset(a5)
popm.l a0-a3/a6/d0-d3
rts
; Assume this bit is called only when:
; a Tuple is to be removed; there are chunks in the list;
; list is consistant and correct (very important);
; a1=^last chunk; d1=LastTupOffset;
; a0=^chunk; d0=offset (from a0) of any non-NULL tuple in list
; If these rules are obeyed, we won't deallocate current node.
.removescrn tst.w d1
bne.s .dataleft ; \ If LastTupleOffset==NULL, deallocate
pushm.l a0/d0 ; / the last chunk
move.l LN_SUCC(a1),a0 ; a0 <- tail of list
move.l LN_PRED(a1),a3 ; a3 <- last chunk but one
move.l a0,LN_SUCC(a3)
move.l a3,LN_PRED(a0)
move.l #Chunk_SIZEOF,d0
just FreeMem
lea (a3),a1 ; Now get the _new_ last chunk
move.l #Chunk_SIZEOF-Tuple_SIZEOF,d1
popm.l a0/d0
.dataleft move.l Tuple_Screen(a1,d1.w),Tuple_Screen(a0,d0.w)
move.l Tuple_Window(a1,d1.w),Tuple_Window(a0,d0.w)
clr.l Tuple_Screen(a1,d1.w) ; | Replace this tuple with
clr.l Tuple_Window(a1,d1.w) ; / the last one in the table
subq.w #Tuple_SIZEOF,d1
rts